<?php
namespace SimpleMVC\lib;

class Model {
    
    private $tableName;
    private $joins = array();
    private $fields = '*';
    private $where = '';
    private $order = '';
    
    public function table($tableName)
    {
        $this->tableName = $tableName;
        $this->joins = array();
        $this->fields = '*';
        $this->where = '';
        $this->order = '';
        return $this;
    }
    
    public function fields($fields)
    {
        if (is_string($fields)) {
            $this->fields = $fields;
        } else if (is_array($fields)) {
            $this->fields = implode(',', $fields);
        }
        return $this;
    }
    
    public function leftJoin($tableName, $condition)
    {
        $this->join('LEFT', $tableName, $condition);
        return $this;
    }
    
    public function innerJoin($tableName, $condition)
    {
        $this->join('INNER', $tableName, $condition);
        return $this;
    }
    
    private function join($type, $tableName, $condition)
    {
        $join = "$type JOIN $tableName ON ";
        if (is_string($condition)) {
            $join .= $condition;
        } else if (is_array($condition)) {
            $pairs = array();
            foreach ($condition as $key => $value) {
                $pairs[] = "$key = " . $this->preProcessValue($value);
            }
            $join .= implode(' AND ', $pairs);
        }
        $this->joins[] = $join;
    }
    
    public function where($where)
    {
        if (is_string($where)) {
            $this->where = $where;
        } else if (is_array($where)) {
            $pairs = array();
            foreach ($where as $key => $value) {
                $pairs[] = $key . $this->preProcessValue($value, true);
            }
            $this->where = implode(' AND ', $pairs);
        } else {
            $this->where = '';
        }
        return $this;
    }
    
    public function order($order)
    {
        if (is_string($order)) {
            $this->order = 'ORDER BY ' . $order;
        } else if (is_array($order)) {
            $pairs = array();
            foreach ($order as $key => $value) {
                $pairs[] = "$key $value";
            }
            $this->order = 'ORDER BY ' . implode(',', $pairs);
        }
        return $this;
    }
    
    public function selectAll()
    {
        $sql = "SELECT {$this->fields} FROM {$this->tableName}";
        if (!empty($this->joins)) {
            $sql .= ' ' . implode(' ', $this->joins);
        }
        if (!empty($this->where)) {
            $sql .= " WHERE $this->where";
        }
        $sql .= " {$this->order}";
        return Dao::getConnection()->getAll($sql);
    }
    
    public function selectOne()
    {
        $sql = "SELECT {$this->fields} FROM {$this->tableName}";
        if (!empty($this->joins)) {
            $sql .= ' ' . implode(' ', $this->joins);
        }
        if (!empty($this->where)) {
            $sql .= " WHERE $this->where";
        }
        $sql .= " {$this->order} LIMIT 1";
        return Dao::getConnection()->getRow($sql);
    }
    
    public function insert(array $data)
    {
        $keys = array_keys($data);
        $values = $this->preProcessValues(array_values($data));
        $sql = "INSERT {$this->tableName}(" . implode(',', $keys) . ') VALUE(' . implode(',', $values) . ')';
        return Dao::getConnection()->execute($sql);
    }
    
    public function insertBatch(array $rows)
    {
        $valuesList = array();
        $keys = array();
        foreach ($rows as $row) {
            $keys = array_keys($row);
            $values = $this->preProcessValues(array_values($row));
            $valuesList[] = "(" . implode(',', $values) . ")";
        }
        $sql = "INSERT {$this->tableName}(" . implode(',', $keys) . ') VALUES' . implode(',', $valuesList);
        return Dao::getConnection()->execute($sql);
    }
    
    public function update(array $data)
    {
        $pairs = array();
        foreach ($data as $key => $value) {
            $value = $this->preProcessValue($value, false);
            $pairs[] = "$key = $value";
        }
        $sql = "UPDATE {$this->tableName} SET " . implode(',', $pairs) . ' WHERE ' . $this->where;
        return Dao::getConnection()->execute($sql);
    }
    
    private function preProcessValues(array $values)
    {
        foreach ($values as $index => $value) {
            $values[$index] = $this->preProcessValue($value, false); 
        }
        return $values;
    }
    
    private function preProcessValue($value, $isCondition)
    {
        if (is_string($value)) {
            $value = "'" . addslashes($value) . "'";
            return $isCondition ? " = $value" : $value;
        } else if (is_null($value)) {
            return $isCondition ? 'IS NULL' : 'NULL';
        } else {
            return $isCondition ? " = $value" : $value;
        }
    }
    
}
